package roborally;
import static org.junit.Assert.*;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import roborally.Commands.Move;
import roborally.Commands.Turn;
import roborally.Conditions.Energy_at_least;
import roborally.Exceptions.IllegalAmountException;
import roborally.commandCombiners.If;
import roborally.model.Facade;

/**
 * This is the testsuite for the class Robot.
 * 
 * @version  2.90
 * @author   Michiel Ruelens & Dieter Naten
 */

public class RobotTest {
	
	private static Robot energylessRobot;
	private static Robot energyfullRobot;
	
	/**
	 * 		   Set up an immutable test Robot. This robot will act as a fixed point to which other robots are going to move.
	 * 
	 * @post   The variable energylessRobot references a new Robot with 0 energy,
	 * 		   located at (5,5) facing up (0,North,to the top).
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		Board board = new Board(1000,2000);
		energylessRobot = new Robot(board, 5, 5, 0, 0, 20000);
		
	}
	
	@Before
	public void setUp() throws Exception {
		Board board = new Board(1000,2000);
		energylessRobot = new Robot(board, 5,5,0,1000,20000);
		energyfullRobot = new Robot(board, 5,5,0,20000,20000);
		board = new Board(1000,2000);
		shortestPathAlgorithm.clearAlgorithm();
		Node.clearNodeList();
	}


	private Robot robotTopLeftSufficientEnergy, robotTopRightSufficientEnergy, robotBottomLeftSufficientEnergy,robotBottomrightSufficientEnergy, //Normal Cases
				  robotToTopSufficientEnergy,	robotToBottomSufficientEnergy, robotToLeftSufficientEnergy,	   robotToRightSufficientEnergy;	 //Special Cases
	private Board board;
	
	@Test
	public final void testConstructor() {
		Board board = new Board(1000,2000);
		Robot newRobot = new Robot(board, 3,6,2,1500,20000);
		assertNotNull(newRobot);
		assertEquals(3, newRobot.getX());
		assertEquals(6, newRobot.getY());
		assertEquals(2, newRobot.getOrientation());
		assertEquals(1500, newRobot.getEnergy(),0.1);
	}
	
	@Test
	public final void testCosts(){
		Board board1 = new Board(1000,2000);
		Robot newRobot = new Robot(board1, 3,6,2,1500,20000);
		assertEquals(500, newRobot.getCostToMove());
		assertEquals(100, newRobot.getCostToTurn());
		assertEquals(1000, newRobot.getCostToShoot());
		Battery battery = new Battery(1500,1500);
		battery.putBattery(newRobot.getBoard(), newRobot.getX(), newRobot.getY());
		newRobot.pickUp(battery);
		assertEquals(575, newRobot.getCostToMove());
		assertEquals(100, newRobot.getCostToTurn());
		assertEquals(1000, newRobot.getCostToShoot());
		newRobot.setCostToTurn(300);
		assertEquals(300, newRobot.getCostToTurn());
	}
	
	@Test
	public final void testValidationMethods() {
		Board board = new Board(1000,2000);
		Energy energy = new Energy(20000, EnergyUnit.WATTSECOND);
		assertEquals(true, Coordinate.isValidXCoordinate(board,3));
		assertEquals(true, Coordinate.isValidYCoordinate(board,6));
		assertEquals(true, Orientation.isValidOrientation(Orientation.TOP));
		assertEquals(true, Energy.isValidEnergyAmount(1500,EnergyUnit.WATTSECOND,energy));
		Energy energy1 = new Energy(20000,EnergyUnit.WATTSECOND);
		assertEquals(true, Energy.isValidMaxEnergyAmount(energy1,Double.MAX_VALUE));
		assertEquals(true, Robot.isAddableEnergyAmount(500, 20000, 1000));
		
		assertEquals(false, Coordinate.isValidXCoordinate(board,-5));
		assertEquals(false, Coordinate.isValidYCoordinate(board,-10));
		assertEquals(false, Orientation.isValidOrientation(null));
		assertEquals(false, Energy.isValidEnergyAmount(500000,EnergyUnit.WATTSECOND,energy));
		assertEquals(false, Energy.isValidEnergyAmount(-5000,EnergyUnit.WATTSECOND,energy));
		Energy energy2 = new Energy(-1000,EnergyUnit.WATTSECOND);
		assertEquals(false, Energy.isValidMaxEnergyAmount(energy2,Double.MAX_VALUE));
		assertEquals(false, Robot.isAddableEnergyAmount(50000000, 20000, 1000));
	}
	
	@Test
	public final void testGetEnergyMethods() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,0,1000,20000);
		assertEquals(1000, testRobot.getEnergy(),0.1);
		assertEquals(20000, testRobot.getMaxEnergy().toUnit(EnergyUnit.WATTSECOND).getNumeral(),0.1);
		assertEquals(1/20, testRobot.getFractionEnergy(),0.1);
	}
	
	@Test
	public final void testMoveSufficientEnergy() {
		Board board = new Board(1000,2000);
		//move positive X
		Robot testRobot = new Robot(board, 10,20,1,1000,20000);
		testRobot.move();
		assertEquals(11, testRobot.getX());
		
		//move positive Y
		Robot testRobot2 = new Robot(board, 10,20,2,1000,20000);
		testRobot2.move();
		assertEquals(21, testRobot2.getY());
		
		//move negative X
		Robot testRobot3 = new Robot(board, 10,20,3,1000,20000);
		testRobot3.move();
		assertEquals(9, testRobot3.getX());
		
		//move negative Y
		Robot testRobot4 = new Robot(board, 10,20,0,1000,20000);
		testRobot4.move();
		assertEquals(19, testRobot4.getY());
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void testSubtractXException() throws IllegalAmountException {	
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 0,20,3,5000,20000);
		testRobot.move();
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void testSubtractYException() throws IllegalAmountException {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 0,0,0,5000,20000);
		testRobot.move();
	}
	
	
	
	@Test
	public final void testTurningMethods() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,5000,20000);
		testRobot.turnClockwise();
		assertEquals(2, testRobot.getOrientation());
		testRobot.turnClockwise(2);
		assertEquals(0, testRobot.getOrientation());
		testRobot.turnAntiClockwise();
		assertEquals(3, testRobot.getOrientation());
		testRobot.turnAntiClockwise(3);
		assertEquals(0, testRobot.getOrientation());
	}
	
	@Test
	public final void testRecharge() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,0,20000);
		assertEquals(0, testRobot.getEnergy(),0.1);
		testRobot.recharge(500);
		assertEquals(500, testRobot.getEnergy(),0.1);
		testRobot.setEnergy(new Energy(1000,EnergyUnit.JOULE));
		testRobot.recharge(500);
		assertEquals(1500, testRobot.getEnergy(),0.1);
	}
	
	@Test
	public final void testTerminate() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,0,20000);
		Battery battery = new Battery(1500,1500);
		testRobot.addCarryableToPossessions(battery);
		testRobot.terminate();
		assertTrue(testRobot.getAllPossessions().isEmpty());
		assertEquals(true,testRobot.isTerminated());
		assertEquals(true,battery.isTerminated());
	}
	
	@Test
	public final void testUse() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,0,20000);
		assertEquals(0,testRobot.getEnergy(),0.1);
		Battery battery = new Battery(1500,1500);
		RepairKit repair = new RepairKit(1500,1500);
		RepairKit repair2 = new RepairKit(1500,1500);
		SurpriseBox surprise = new SurpriseBox(1500);
		testRobot.addCarryableToPossessions(battery);
		testRobot.addCarryableToPossessions(repair);
		testRobot.addCarryableToPossessions(repair2);
		testRobot.addCarryableToPossessions(surprise);
		testRobot.useCarryable(battery);
		assertEquals(1500,testRobot.getEnergy(),0.1);
		repair.terminate();
		testRobot.useCarryable(repair);
		assertEquals(20000,testRobot.getMaxEnergy().getNumeral(),0.1);
		testRobot.useCarryable(repair2);
		assertEquals(20000,testRobot.getMaxEnergy().getNumeral(),0.1);
		testRobot.setMaxEnergy(new Energy(10000, EnergyUnit.WATTSECOND));
		testRobot.useCarryable(repair2);
		assertEquals(10750,testRobot.getMaxEnergy().getNumeral(),0.1);
		testRobot.useCarryable(surprise);
	}
	
	@Test
	public final void testTransfer() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,0,20000);
		Robot testRobot2 = new Robot(board, 11,20,1,0,20000);
		Battery battery = new Battery(1500,1500);
		RepairKit repair = new RepairKit(1500,1500);
		SurpriseBox surprise = new SurpriseBox(1500);
		testRobot.addCarryableToPossessions(battery);
		testRobot.addCarryableToPossessions(repair);
		testRobot.addCarryableToPossessions(surprise);
		assertEquals(3,testRobot.getAllPossessions().size());
		assertTrue(testRobot.getAllPossessions().contains(battery));
		assertTrue(testRobot.getAllPossessions().contains(repair));
		assertTrue(testRobot.getAllPossessions().contains(surprise));
		testRobot.transfersCarryables(testRobot2);
		assertEquals(0,testRobot.getAllPossessions().size());
		assertFalse(testRobot.getAllPossessions().contains(battery));
		assertFalse(testRobot.getAllPossessions().contains(repair));
		assertFalse(testRobot.getAllPossessions().contains(surprise));
		assertEquals(3,testRobot2.getAllPossessions().size());
		assertTrue(testRobot2.getAllPossessions().contains(battery));
		assertTrue(testRobot2.getAllPossessions().contains(repair));
		assertTrue(testRobot2.getAllPossessions().contains(surprise));
;	}
	
	@Test
	public final void testIsGetEnergyRequiredToReachAndMoveNextTo16Plus() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 10,20,1,0,20000);
		assertEquals(1, testRobot.isGetEnergyRequiredToReachAndMoveNextTo16Plus());
	}
	
	@Test
	public final void testGetEnergyRequiredToReachBottomRight1() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 0,0,1,20000,20000);
		assertEquals(5100,testRobot.getEnergyRequiredToReach(5, 5),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachBottomRight2() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 0,0,2,20000,20000);
		assertEquals(5100,testRobot.getEnergyRequiredToReach(5, 5),0.1);
	}
	@Test
	public final void testGetEnergyRequiredToReachTopRight() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 0,5,3,20000,20000);
		assertEquals(5200,testRobot.getEnergyRequiredToReach(5, 0),0.1);
	}
	
	@Test
	public final void testGetEnergyRequiredToReachTopLeft() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,20000,20000);
		assertEquals(5100,testRobot.getEnergyRequiredToReach(0, 0),0.1);
	}
	
	@Test
	public final void testGetEnergyRequiredToReachBottomLeft() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,20000,20000);
		assertEquals(5200,testRobot.getEnergyRequiredToReach(0, 10),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachToTop() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 20,20,2,20000,20000);
		assertEquals(2700,testRobot.getEnergyRequiredToReach(20, 15),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachToBottom() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 20,20,3,20000,20000);
		assertEquals(4100,testRobot.getEnergyRequiredToReach(20, 12),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachToLeft() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 20,20,1,20000,20000);
		assertEquals(3200,testRobot.getEnergyRequiredToReach(14, 20),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachToRight() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 20,20,0,20000,20000);
		assertEquals(3100,testRobot.getEnergyRequiredToReach(26, 20),0.1);
	}

	@Test
	public final void testGetEnergyRequiredToReachOnSamePlace() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 20,20,3,20000,20000);
		assertEquals(0,testRobot.getEnergyRequiredToReach(20, 20),0.1);
	}
	
	//THE FOLLOWING IS A MASSIVE TEST LIST FOR MOVE NEXT TO, GOING THROUGH EACH POSSIBLE CASE.
	//EVERY TIME THE METHODE MOVENEXTTO() IS CALLED TWICE, SWITCHING THE ROBOTS PLACES IN THE ARGUMENTS
	
	//THIS LIST GOES THROUGH ALL POSSIBLE CASES AND ONLY 1 OF THE ROBOTS CAN MOVE
	@Test
	public final void testMoveNextToCaseBottomRight1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,0,20000);
		Robot testRobot2 = new Robot(board, 0,0,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	
		Robot testRobot3 = new Robot(board, 5,5,1,0,20000);
		Robot testRobot4 = new Robot(board, 0,0,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));}
	
	@Test
	public final void testMoveNextToCaseTopLeft1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 0,0,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 0,0,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseTopRight1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 10,1,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 10,1,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseBottomLeft1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,0,20000);
		Robot testRobot2 = new Robot(board, 10,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,0,20000);
		Robot testRobot4 = new Robot(board, 10,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	@Test
	public final void testMoveNextToCaseToTop1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));	
	}
	
	@Test
	public final void testMoveNextToCaseToBottom1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,0,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,0,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}

	@Test
	public final void testMoveNextToCaseToLeft1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,1,1,0,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,1,1,0,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	@Test
	public final void testMoveNextToCaseToRight1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseAlreadyNextToEachOther1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,2,1,20000,20000);
		Robot testRobot2 = new Robot(board, 1,1,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,2,1,20000,20000);
		Robot testRobot4 = new Robot(board, 1,1,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseOnTopOfEachOther1CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot2 = new Robot(board, 1,1,1,0,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot4 = new Robot(board, 1,1,1,0,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	//THIS LIST GOES THROUGH ALL THE CASES AND BOTH ROBOTS CAN MOVE.
	
	@Test
	public final void testMoveNextToCaseBottomRightAndTopLeft2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 0,0,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 0,0,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	@Test
	public final void testMoveNextToCaseTopRightAndBottomLeft2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 10,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 10,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	@Test
	public final void testMoveNextToCaseToTopAndToBottom2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 5,5,1,20000,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}


	@Test
	public final void testMoveNextToCaseToLeftAndToRight2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot2 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot4 = new Robot(board, 5,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}

	
	@Test
	public final void testMoveNextToCaseAlreadyNextToEachOther2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,2,1,20000,20000);
		Robot testRobot2 = new Robot(board, 1,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,2,1,20000,20000);
		Robot testRobot4 = new Robot(board, 1,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	@Test
	public final void testMoveNextToCaseOnTopOfEachOther2CanMove() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot2 = new Robot(board, 1,1,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		
		Robot testRobot3 = new Robot(board, 1,1,1,20000,20000);
		Robot testRobot4 = new Robot(board, 1,1,1,20000,20000);
		testRobot.moveNextTo(testRobot4, testRobot3);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
		}
	
	//TESTING SPECIFIC SPECIAL CASES OF POSITIONING AND ORIENTATION TO COVER ALL POSSIBILITIES
	
	@Test
	public final void testMoveNextToCaseRobot2IsMoreFavorableTopRight() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,3,20000,20000);
		Robot testRobot2 = new Robot(board, 10,1,2,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseRobot2IsMoreFavorableBottomRight() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,3,20000,20000);
		Robot testRobot2 = new Robot(board, 10,10,3,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseRobot2IsMoreFavorableToBottom() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,20000,20000);
		Robot testRobot2 = new Robot(board, 5,10,3,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseRobot2IsMoreFavorableToRight() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,3,20000,20000);
		Robot testRobot2 = new Robot(board, 10,5,3,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseBothCanMove3rdFavoriteOrientation1() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,20000,20000);
		Robot testRobot2 = new Robot(board, 10,10,2,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseBothCanMove3rdFavoriteOrientation2() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,3,20000,20000);
		Robot testRobot2 = new Robot(board, 10,10,2,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseBothCanMove3rdFavoriteOrientationSpecialCase1() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,3,20000,20000);
		Robot testRobot2 = new Robot(board, 5,10,2,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseBothCanMove3rdFavoriteOrientationSpecialCase2() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,20000,20000);
		Robot testRobot2 = new Robot(board, 5,10,2,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseRobot1isMoveFavorableButInsufficientEnergy() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,500,20000);
		Robot testRobot2 = new Robot(board, 10,10,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}
	
	@Test
	public final void testMoveNextToCaseRobot1isMoveFavorableButInsufficientEnergySpecialCase() {
		Board board = new Board(1000,2000);
		Robot testRobot = new Robot(board, 5,5,0,500,20000);
		Robot testRobot2 = new Robot(board, 5,10,1,20000,20000);
		testRobot.moveNextTo(testRobot, testRobot2);
		assertTrue(Coordinate.standNextToEachOther(testRobot.getCoordinate(),testRobot2.getCoordinate()));
	}

	// VAN ANDERE
	
	@Test
	public void testMoveNextToFullEnergyRobot(){
		Board board = energyfullRobot.getBoard();
		Robot robot = new Robot(board,0,0,0,0,20000);
		Robot robot2 = new Robot(board,5,5,0,20000,20000);
		double initialEnergy = robot2.getEnergy();
		Wall wall1 = new Wall();
		Wall wall2 = new Wall();
		Wall wall3 = new Wall();
		Wall wall4 = new Wall();
		Wall wall5 = new Wall();
		Wall wall6 = new Wall();
		Wall wall7 = new Wall();
		Wall wall8 = new Wall();
		Wall wall9 = new Wall();
		wall1.putWall(board,1,0);
		wall2.putWall(board,1,1);
		wall3.putWall(board,1,2);
		wall4.putWall(board,0,4);
		wall5.putWall(board,1,4);
		wall6.putWall(board,2,4);
		wall7.putWall(board,3,4);
		wall8.putWall(board,3,3);
		wall9.putWall(board,3,2);
		
		shortestPathAlgorithm.clearAlgorithm();
		Node.clearNodeList();
		List<Node> path = shortestPathAlgorithm.getShortestPath(robot2, robot.getCoordinate(), 
																Orientation.convertIntToOrientation(robot2.getOrientation()), 
																robot2.getEnergy(), robot2.getBoard());
		//The pathlist includes the startnode and endnode
		assertEquals(15,path.size());
		robot.moveNextTo(robot, robot2);
		//The path required 13 moves(6500) and 4 turns(400) so 6900 energy.
		assertTrue(initialEnergy==robot2.getEnergy()+6900);
		assertTrue(Coordinate.standNextToEachOther(robot2.getCoordinate(),robot.getCoordinate()));

	}
	
	@Test
	public void testMoveNextToNearEdgeOfBoard(){
		Board board = energyfullRobot.getBoard();
		Robot robot = new Robot(board,0,0,0,20000,20000);
		Robot robot2 = new Robot(board, 0,10,0,20000,20000);
		robot.moveNextTo(robot, robot2);
		assertTrue(Coordinate.standNextToEachOther(robot.getCoordinate(), robot2.getCoordinate()));
		assertTrue(robot.getEnergy()==(20000-4700));
		assertTrue(robot2.getEnergy()==20000);
	}
	
	@Test
	public void testMoveNextToNearEdgeOfBoardOtherWayAround(){
		Board board = energyfullRobot.getBoard();
		Robot robot = new Robot(0,20000);
		robot.putRobot(board, 0, 0);
		Robot robot2 = new Robot(0,20000);
		robot2.putRobot(board,0,10);
		robot.moveNextTo(robot2, robot);
		assertTrue(Coordinate.standNextToEachOther(robot.getCoordinate(), robot2.getCoordinate()));
		assertTrue(robot.getEnergy()==20000);
		assertTrue(robot2.getEnergy()==20000-4500);
	}
	
	@Test
	public void testGetIthHeaviestCarryable(){
		Board board = new Board(1000,1000);
		Robot robot = new Robot(1,5000);
		robot.putRobot(board,5,5);
		Battery b1 = new Battery(100,1000);
		Battery b2 = new Battery(200,2000);
		Battery b3 = new Battery(300,3000);
		Battery b4 = new Battery(400,4000);
		Battery b5 = new Battery(500,5000);
		b1.putBattery(board, 5, 5);
		b2.putBattery(board, 5, 5);
		b3.putBattery(board, 5, 5);
		b4.putBattery(board, 5, 5);
		b5.putBattery(board, 5, 5);
		robot.pickUp(b1);
		robot.pickUp(b2);
		robot.pickUp(b3);
		robot.pickUp(b4);
		robot.pickUp(b5);
		assertTrue(robot.getIthHeaviestPossession(1)==b1);
		assertTrue(robot.getIthHeaviestPossession(2)==b2);
		assertTrue(robot.getIthHeaviestPossession(3)==b3);
		assertTrue(robot.getIthHeaviestPossession(4)==b4);
		assertTrue(robot.getIthHeaviestPossession(5)==b5);
	}
	
	@Test
	public void testRobotPossessions() {
		Board board = energyfullRobot.getBoard();
		Battery battery = new Battery(500,100);
		battery.putBattery(board,5,5);
		energyfullRobot.addCarryableToPossessions(battery);
		List<? extends Placeable> possessions = energyfullRobot.getAllPossessions();
		assert(possessions != null);
		assert(possessions.size() == 1);
		assert(possessions.contains(battery));
	}
	
	@Test
	public void testRobotPossessions2(){
		Board board = energyfullRobot.getBoard();
		Battery battery = new Battery(500,100);
		battery.putBattery(board,5,5);
		energyfullRobot.addCarryableToPossessions(battery);
		Set<? extends Carryable> possessions = energyfullRobot.getAllPossessionsByType(PlaceableType.BATTERY);
		assert(possessions.size()==1);
		assert(possessions!=null);
	}
	
	@Test
	public void testRobotPickUpBattery() {
		Board board = energyfullRobot.getBoard();
		Battery battery = new Battery(500,100);
		battery.putBattery(board,5,4);
		assert(board.getAllObjectsByType(PlaceableType.BATTERY).contains(battery));
		assert(board.hasPlaceableAtPosition(5, 5));
		assert(board.hasPlaceableAtPosition(5, 4));
		energyfullRobot.move();
		energyfullRobot.pickUp(battery);
		List<? extends Placeable> possessions = energyfullRobot.getAllPossessions();
		assert(possessions != null);
		assert(possessions.size() == 1);
		assert(possessions.contains(battery));
		energyfullRobot.move();
		assert(board.hasPlaceableAtPosition(5,3));
		assertFalse(board.hasPlaceableAtPosition(5, 4));
		assertFalse(board.getAllObjectsByType(PlaceableType.BATTERY).contains(battery));
	}
	
	@Test
	public void testRobotDropBattery(){
		Board board = energyfullRobot.getBoard();
		Battery battery = new Battery(500,100);
		battery.putBattery(board,5,5);
		energyfullRobot.pickUp(battery);
		energyfullRobot.move();
		energyfullRobot.drop(battery);
		energyfullRobot.move();
		assert(board.hasPlaceableAtPosition(5, 3));
		assert(board.hasPlaceableAtPosition(5, 4));
		Set<Placeable>	set1 = (Set<Placeable>) board.getAllObjectsByType(PlaceableType.BATTERY);
		assert(set1.contains(battery));
		Set<Placeable> set2 = (Set<Placeable>) board.getAllObjectsByPosition(5,4);
		assert(set2.contains(battery));
	}
	
	/**
	 * TODO
	 * THE FOLLOWING METHOD DOES NOT WORK YET BECAUSE IT USE THE MOVE METHOD
	 * AND IT DOES NOT YET TAKE INTO ACCOUNT THAT THE HASHMAPS OF THE BOARD NEED
	 * TO CHANGE WHEN A ROBOT MOVES AROUND THE BOARD.
	 */
	@Test
	public void testRobotShoot(){
		Board board = energyfullRobot.getBoard();
		energylessRobot.recharge(1000);
		energylessRobot.move();
		energylessRobot.move();
		Set<Placeable> set = board.getAllObjectsByPosition(5, 3);
		assertTrue(board.hasPlaceableAtPosition(5, 3));
		assertTrue(board.hasPlaceableAtPosition(5, 5));
		Double maxEnergyInWSBefore = energylessRobot.getMaxEnergy().toUnit(EnergyUnit.WATTSECOND).getNumeral();
		energyfullRobot.shoot();
		assertTrue((maxEnergyInWSBefore-4000)==(energylessRobot.getMaxEnergy().toUnit(EnergyUnit.WATTSECOND).getNumeral()));
		}
	
	@Test
	public void testTeleport(){
		Board board = new Board(Long.MAX_VALUE,Long.MAX_VALUE);
		Robot robot = new Robot(1,5000);
		robot.putRobot(board,5,5);	
		SurpriseBox surpriseBox = new SurpriseBox(1500);	
		surpriseBox.putSurpriseBox(board, 5, 5);
		surpriseBox.teleport(robot);
	}
	
	@Test
	public void testProgram(){
		Robot robot = new Robot(new Board(2000,2000), 5,5,0,10000,20000);
		List<Statement> statementList = new ArrayList<Statement>();
		statementList.add(new Move());
		statementList.add(new If(Energy_at_least.getInstance(1000), new Turn(Rotation.Clockwise), new Move()));
		Program program = new Program(statementList);
		assertTrue(robot.getOrientation()==0);
		assertTrue(robot.getX()==5);
		Facade f = new Facade();
		robot.setProgram(program);
		f.prettyPrintProgram(robot, new StringWriter());
		Program.executeProgram(robot, program);
		assertTrue(robot.getOrientation()==1);
		assertTrue(robot.getY()==4);
		
	}
	
}
